/*     */ package com.zimbra.cs.db;
/*     */ 
/*     */ import com.google.common.collect.HashMultimap;
/*     */ import com.google.common.collect.Multimap;
/*     */ import com.zimbra.common.localconfig.DebugConfig;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.store.file.BlobConsistencyChecker.BlobInfo;
/*     */ import com.zimbra.cs.store.file.FileBlobStore;
/*     */ import java.sql.PreparedStatement;
/*     */ import java.sql.ResultSet;
/*     */ import java.sql.SQLException;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Collection;
/*     */ import java.util.HashSet;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Set;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class DbBlobConsistency
/*     */ {
/*     */   public static Collection<BlobConsistencyChecker.BlobInfo> getBlobInfo(DbPool.DbConnection conn, Mailbox mbox, int minId, int maxId, short volumeId)
/*     */     throws ServiceException
/*     */   {
/*  46 */     PreparedStatement stmt = null;
/*  47 */     ResultSet rs = null;
/*  48 */     List<BlobConsistencyChecker.BlobInfo> blobs = new ArrayList();
/*     */     try
/*     */     {
/*  51 */       stmt = conn.prepareStatement("SELECT id, mod_content, 0, size FROM " + DbMailItem.getMailItemTableName(mbox, false) + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + " id BETWEEN " + minId + " AND " + maxId + " AND blob_digest IS NOT NULL " + "AND locator = " + volumeId + " UNION " + "SELECT id, mod_content, 0, size " + "FROM " + DbMailItem.getMailItemTableName(mbox, true) + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + " id BETWEEN " + minId + " AND " + maxId + " AND blob_digest IS NOT NULL " + "AND locator = " + volumeId + " UNION " + "SELECT item_id, mod_content, version, size " + "FROM " + DbMailItem.getRevisionTableName(mbox, false) + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + " item_id BETWEEN " + minId + " AND " + maxId + " AND blob_digest IS NOT NULL " + "AND locator = " + volumeId + " UNION " + "SELECT item_id, mod_content, version, size " + "FROM " + DbMailItem.getRevisionTableName(mbox, true) + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + " item_id BETWEEN " + minId + " AND " + maxId + " AND blob_digest IS NOT NULL " + "AND locator = " + volumeId);
/*     */       
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  79 */       if (!DebugConfig.disableMailboxGroups) {
/*  80 */         stmt.setInt(1, mbox.getId());
/*  81 */         stmt.setInt(2, mbox.getId());
/*  82 */         stmt.setInt(3, mbox.getId());
/*  83 */         stmt.setInt(4, mbox.getId());
/*     */       }
/*  85 */       Db.getInstance().enableStreaming(stmt);
/*  86 */       rs = stmt.executeQuery();
/*  87 */       while (rs.next()) {
/*  88 */         BlobConsistencyChecker.BlobInfo info = new BlobConsistencyChecker.BlobInfo();
/*  89 */         info.itemId = rs.getInt(1);
/*  90 */         info.modContent = rs.getInt(2);
/*  91 */         info.version = rs.getInt(3);
/*  92 */         info.dbSize = rs.getLong(4);
/*  93 */         info.volumeId = volumeId;
/*  94 */         info.path = FileBlobStore.getBlobPath(mbox, info.itemId, info.modContent, volumeId);
/*  95 */         blobs.add(info);
/*     */       }
/*     */     } catch (SQLException e) {
/*  98 */       throw ServiceException.FAILURE("getting items with blobs for mailbox " + mbox.getId(), e);
/*     */     } finally {
/* 100 */       DbPool.closeResults(rs);
/* 101 */       DbPool.quietCloseStatement(stmt);
/*     */     }
/*     */     
/* 104 */     return blobs;
/*     */   }
/*     */   
/*     */   public static Collection<BlobConsistencyChecker.BlobInfo> getExternalMailItemBlobInfo(DbPool.DbConnection conn, Mailbox mbox, int minId, int maxId) throws ServiceException
/*     */   {
/* 109 */     return getExternalMailItemBlobInfo(conn, mbox, minId, maxId, false);
/*     */   }
/*     */   
/*     */   public static Collection<BlobConsistencyChecker.BlobInfo> getExternalMailItemDumpsterBlobInfo(DbPool.DbConnection conn, Mailbox mbox, int minId, int maxId) throws ServiceException {
/* 113 */     return getExternalMailItemBlobInfo(conn, mbox, minId, maxId, true);
/*     */   }
/*     */   
/*     */   private static Collection<BlobConsistencyChecker.BlobInfo> getExternalMailItemBlobInfo(DbPool.DbConnection conn, Mailbox mbox, int minId, int maxId, boolean dumpster) throws ServiceException {
/* 117 */     String query = "SELECT id, mod_content, 0, size, locator FROM " + DbMailItem.getMailItemTableName(mbox, dumpster) + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + " id BETWEEN " + minId + " AND " + maxId + " AND blob_digest IS NOT NULL";
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 122 */     return getExternalBlobInfo(conn, mbox, query);
/*     */   }
/*     */   
/*     */   public static Collection<BlobConsistencyChecker.BlobInfo> getExternalRevisionBlobInfo(DbPool.DbConnection conn, Mailbox mbox, int minId, int maxId) throws ServiceException {
/* 126 */     return getExternalRevisionBlobInfo(conn, mbox, minId, maxId, false);
/*     */   }
/*     */   
/*     */   public static Collection<BlobConsistencyChecker.BlobInfo> getExternalRevisionDumpsterBlobInfo(DbPool.DbConnection conn, Mailbox mbox, int minId, int maxId) throws ServiceException {
/* 130 */     return getExternalRevisionBlobInfo(conn, mbox, minId, maxId, true);
/*     */   }
/*     */   
/*     */   private static Collection<BlobConsistencyChecker.BlobInfo> getExternalRevisionBlobInfo(DbPool.DbConnection conn, Mailbox mbox, int minId, int maxId, boolean dumpster) throws ServiceException {
/* 134 */     String query = "SELECT item_id, mod_content, version, size, locator FROM " + DbMailItem.getRevisionTableName(mbox, dumpster) + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + " item_id BETWEEN " + minId + " AND " + maxId + " AND blob_digest IS NOT NULL";
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 139 */     return getExternalBlobInfo(conn, mbox, query);
/*     */   }
/*     */   
/*     */   private static Collection<BlobConsistencyChecker.BlobInfo> getExternalBlobInfo(DbPool.DbConnection conn, Mailbox mbox, String query) throws ServiceException
/*     */   {
/* 144 */     PreparedStatement stmt = null;
/* 145 */     ResultSet rs = null;
/* 146 */     List<BlobConsistencyChecker.BlobInfo> blobs = new ArrayList();
/*     */     try
/*     */     {
/* 149 */       stmt = conn.prepareStatement(query);
/* 150 */       if (!DebugConfig.disableMailboxGroups) {
/* 151 */         stmt.setInt(1, mbox.getId());
/*     */       }
/* 153 */       Db.getInstance().enableStreaming(stmt);
/* 154 */       rs = stmt.executeQuery();
/* 155 */       while (rs.next()) {
/* 156 */         BlobConsistencyChecker.BlobInfo info = new BlobConsistencyChecker.BlobInfo();
/* 157 */         info.itemId = rs.getInt(1);
/* 158 */         info.modContent = rs.getInt(2);
/* 159 */         info.version = rs.getInt(3);
/* 160 */         info.dbSize = rs.getLong(4);
/* 161 */         info.path = rs.getString(5);
/* 162 */         info.external = true;
/* 163 */         blobs.add(info);
/*     */       }
/*     */     } catch (SQLException e) {
/* 166 */       throw ServiceException.FAILURE("getting items with blobs for mailbox " + mbox.getId(), e);
/*     */     } finally {
/* 168 */       DbPool.closeResults(rs);
/* 169 */       DbPool.quietCloseStatement(stmt);
/*     */     }
/*     */     
/* 172 */     return blobs;
/*     */   }
/*     */   
/*     */ 
/*     */   public static int getMaxId(DbPool.DbConnection conn, Mailbox mbox)
/*     */     throws ServiceException
/*     */   {
/* 179 */     int maxId = 0;
/* 180 */     boolean[] dumpster = { false, true };
/* 181 */     for (boolean fromDumpster : dumpster) {
/* 182 */       PreparedStatement stmt = null;
/* 183 */       ResultSet rs = null;
/*     */       try {
/* 185 */         String sql = "SELECT MAX(id) FROM " + DbMailItem.getMailItemTableName(mbox, fromDumpster);
/*     */         
/* 187 */         if (!DebugConfig.disableMailboxGroups) {
/* 188 */           sql = sql + " WHERE mailbox_id = " + mbox.getId();
/*     */         }
/* 190 */         stmt = conn.prepareStatement(sql);
/* 191 */         rs = stmt.executeQuery();
/* 192 */         rs.next();
/* 193 */         int id = rs.getInt(1);
/* 194 */         maxId = Math.max(id, maxId);
/*     */       } catch (SQLException e) {
/* 196 */         throw ServiceException.FAILURE("getting max id for mailbox " + mbox.getId(), e);
/*     */       } finally {
/* 198 */         DbPool.closeResults(rs);
/* 199 */         DbPool.quietCloseStatement(stmt);
/*     */       }
/*     */     }
/* 202 */     return maxId;
/*     */   }
/*     */   
/*     */   public static int getNumRows(DbPool.DbConnection conn, Mailbox mbox, String tableName, String idColName, Multimap<Integer, Integer> idRevs)
/*     */     throws ServiceException
/*     */   {
/* 208 */     Set<Integer> mail_itemIds = new HashSet();
/* 209 */     Multimap<Integer, Integer> rev_itemIds = HashMultimap.create();
/* 210 */     for (Iterator i$ = idRevs.keySet().iterator(); i$.hasNext();) { itemId = (Integer)i$.next();
/* 211 */       Collection<Integer> revs = idRevs.get(itemId);
/* 212 */       for (i$ = revs.iterator(); i$.hasNext();) { int rev = ((Integer)i$.next()).intValue();
/* 213 */         if (rev == 0) {
/* 214 */           mail_itemIds.add(itemId);
/*     */         } else
/* 216 */           rev_itemIds.put(itemId, Integer.valueOf(rev));
/*     */       } }
/*     */     Integer itemId;
/*     */     Iterator i$;
/* 220 */     PreparedStatement stmt = null;
/* 221 */     ResultSet rs = null;
/*     */     try {
/* 223 */       StringBuffer sql = new StringBuffer();
/* 224 */       boolean revisionTable = tableName.startsWith("revision");
/* 225 */       sql.append("SELECT COUNT(*) FROM ").append(DbMailbox.qualifyTableName(mbox, tableName)).append(" WHERE ").append(DbMailItem.IN_THIS_MAILBOX_AND);
/*     */       
/*     */ 
/*     */ 
/* 229 */       if ((!revisionTable) || (mail_itemIds.size() > 0)) {
/* 230 */         if (mail_itemIds.size() == 0) {
/* 231 */           sql.append(idColName).append(" in ('')");
/*     */         } else {
/* 233 */           sql.append(DbUtil.whereIn(idColName, mail_itemIds.size()));
/*     */         }
/*     */       }
/* 236 */       if (revisionTable) {
/* 237 */         if ((mail_itemIds.size() > 0) && (rev_itemIds.size() > 0)) {
/* 238 */           sql.append(" OR ");
/*     */         }
/*     */         
/* 241 */         if (rev_itemIds.size() > 0) {
/* 242 */           sql.append(DbUtil.whereIn(Db.getInstance().concat(new String[] { idColName, "'-'", "version" }), rev_itemIds.size()));
/*     */         }
/*     */       }
/*     */       
/* 246 */       stmt = conn.prepareStatement(sql.toString());
/* 247 */       int pos = 1;
/* 248 */       pos = DbMailItem.setMailboxId(stmt, mbox, pos);
/*     */       
/* 250 */       for (Iterator i$ = mail_itemIds.iterator(); i$.hasNext();) { int itemId = ((Integer)i$.next()).intValue();
/* 251 */         stmt.setInt(pos++, itemId);
/*     */       }
/*     */       Iterator i$;
/* 254 */       if (revisionTable)
/* 255 */         for (i$ = rev_itemIds.keySet().iterator(); i$.hasNext();) { itemId = (Integer)i$.next();
/* 256 */           Collection<Integer> revs = rev_itemIds.get(itemId);
/* 257 */           for (i$ = revs.iterator(); i$.hasNext();) { int rev = ((Integer)i$.next()).intValue();
/* 258 */             stmt.setString(pos++, itemId + "-" + rev);
/*     */           } }
/*     */       Integer itemId;
/*     */       Iterator i$;
/* 262 */       rs = stmt.executeQuery();
/* 263 */       rs.next();
/* 264 */       return rs.getInt(1);
/*     */     } catch (SQLException e) {
/* 266 */       throw ServiceException.FAILURE("getting number of rows for matching id's in " + tableName, e);
/*     */     } finally {
/* 268 */       DbPool.closeResults(rs);
/* 269 */       DbPool.quietCloseStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */   public static void export(DbPool.DbConnection conn, Mailbox mbox, String tableName, String idColName, Multimap<Integer, Integer> idRevs, String path)
/*     */     throws ServiceException
/*     */   {
/* 276 */     Set<Integer> mail_itemIds = new HashSet();
/* 277 */     Multimap<Integer, Integer> rev_itemIds = HashMultimap.create();
/* 278 */     for (Iterator i$ = idRevs.keySet().iterator(); i$.hasNext();) { itemId = (Integer)i$.next();
/* 279 */       Collection<Integer> revs = idRevs.get(itemId);
/* 280 */       for (i$ = revs.iterator(); i$.hasNext();) { int rev = ((Integer)i$.next()).intValue();
/* 281 */         if (rev == 0) {
/* 282 */           mail_itemIds.add(itemId);
/*     */         } else
/* 284 */           rev_itemIds.put(itemId, Integer.valueOf(rev));
/*     */       } }
/*     */     Integer itemId;
/*     */     Iterator i$;
/* 288 */     PreparedStatement stmt = null;
/*     */     
/* 290 */     if (!(Db.getInstance() instanceof MySQL)) {
/* 291 */       throw ServiceException.INVALID_REQUEST("export is only supported for MySQL", null);
/*     */     }
/* 293 */     ZimbraLog.sqltrace.info("Exporting %d items in table %s to %s.", new Object[] { Integer.valueOf(idRevs.size()), tableName, path });
/*     */     try
/*     */     {
/* 296 */       StringBuffer sql = new StringBuffer();
/* 297 */       boolean revisionTable = tableName.startsWith("revision");
/* 298 */       sql.append("SELECT * FROM ").append(DbMailbox.qualifyTableName(mbox, tableName)).append(" WHERE ").append(DbMailItem.IN_THIS_MAILBOX_AND);
/*     */       
/*     */ 
/*     */ 
/* 302 */       if ((!revisionTable) || (mail_itemIds.size() > 0)) {
/* 303 */         if (mail_itemIds.size() == 0) {
/* 304 */           sql.append(idColName).append(" in ('')");
/*     */         } else {
/* 306 */           sql.append(DbUtil.whereIn(idColName, mail_itemIds.size()));
/*     */         }
/*     */       }
/* 309 */       if (revisionTable) {
/* 310 */         if ((mail_itemIds.size() > 0) && (rev_itemIds.size() > 0)) {
/* 311 */           sql.append(" OR ");
/*     */         }
/* 313 */         if (rev_itemIds.size() > 0) {
/* 314 */           sql.append(DbUtil.whereIn(Db.getInstance().concat(new String[] { idColName, "'-'", "version" }), rev_itemIds.size()));
/*     */         }
/*     */       }
/* 317 */       sql.append(" INTO OUTFILE ?");
/* 318 */       stmt = conn.prepareStatement(sql.toString());
/* 319 */       int pos = 1;
/* 320 */       pos = DbMailItem.setMailboxId(stmt, mbox, pos);
/* 321 */       for (Iterator i$ = mail_itemIds.iterator(); i$.hasNext();) { int itemId = ((Integer)i$.next()).intValue();
/* 322 */         stmt.setInt(pos++, itemId);
/*     */       }
/*     */       Iterator i$;
/* 325 */       if (revisionTable)
/* 326 */         for (i$ = rev_itemIds.keySet().iterator(); i$.hasNext();) { itemId = (Integer)i$.next();
/* 327 */           Collection<Integer> revs = rev_itemIds.get(itemId);
/* 328 */           for (i$ = revs.iterator(); i$.hasNext();) { int rev = ((Integer)i$.next()).intValue();
/* 329 */             stmt.setString(pos++, itemId + "-" + rev);
/*     */           } }
/*     */       Integer itemId;
/*     */       Iterator i$;
/* 333 */       stmt.setString(pos++, path);
/* 334 */       stmt.execute();
/*     */     } catch (SQLException e) {
/* 336 */       throw ServiceException.FAILURE("exporting table " + tableName + " to " + path, e);
/*     */     } finally {
/* 338 */       DbPool.quietCloseStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */   public static void delete(DbPool.DbConnection conn, Mailbox mbox, Multimap<Integer, Integer> idRevs) throws ServiceException
/*     */   {
/* 344 */     Set<Integer> mail_itemIds = new HashSet();
/* 345 */     Multimap<Integer, Integer> rev_itemIds = HashMultimap.create();
/* 346 */     for (Iterator i$ = idRevs.keySet().iterator(); i$.hasNext();) { itemId = (Integer)i$.next();
/* 347 */       Collection<Integer> revs = idRevs.get(itemId);
/* 348 */       for (i$ = revs.iterator(); i$.hasNext();) { int rev = ((Integer)i$.next()).intValue();
/* 349 */         if (rev == 0) {
/* 350 */           mail_itemIds.add(itemId);
/*     */         } else
/* 352 */           rev_itemIds.put(itemId, Integer.valueOf(rev));
/*     */       }
/*     */     }
/*     */     Integer itemId;
/*     */     Iterator i$;
/* 357 */     if (mail_itemIds.size() > 0) {
/* 358 */       PreparedStatement miDumpstmt = null;
/*     */       try {
/* 360 */         StringBuffer sql = new StringBuffer();
/* 361 */         sql.append("DELETE FROM ").append(DbMailItem.getMailItemTableName(mbox, true)).append(" WHERE ").append(DbMailItem.IN_THIS_MAILBOX_AND).append(DbUtil.whereIn("id", mail_itemIds.size()));
/*     */         
/*     */ 
/*     */ 
/* 365 */         miDumpstmt = conn.prepareStatement(sql.toString());
/* 366 */         int pos = 1;
/* 367 */         pos = DbMailItem.setMailboxId(miDumpstmt, mbox, pos);
/* 368 */         for (Iterator i$ = mail_itemIds.iterator(); i$.hasNext();) { int itemId = ((Integer)i$.next()).intValue();
/* 369 */           miDumpstmt.setInt(pos++, itemId);
/*     */         }
/* 371 */         miDumpstmt.execute();
/*     */       } catch (SQLException e) {
/* 373 */         throw ServiceException.FAILURE("deleting " + idRevs.size() + " item(s): " + DbMailItem.getIdListForLogging(idRevs.keys()) + " from " + "mail_item_dumpster" + " table", e);
/*     */       }
/*     */       finally {
/* 376 */         DbPool.quietCloseStatement(miDumpstmt);
/*     */       }
/*     */     }
/*     */     
/* 380 */     if (rev_itemIds.size() > 0) {
/* 381 */       PreparedStatement revDumpstmt = null;
/*     */       try {
/* 383 */         StringBuffer sql = new StringBuffer();
/* 384 */         sql.append("DELETE FROM ").append(DbMailItem.getRevisionTableName(mbox, true)).append(" WHERE ").append(DbMailItem.IN_THIS_MAILBOX_AND).append(DbUtil.whereIn(Db.getInstance().concat(new String[] { "item_id", "'-'", "version" }), rev_itemIds.size()));
/*     */         
/*     */ 
/*     */ 
/*     */ 
/* 389 */         revDumpstmt = conn.prepareStatement(sql.toString());
/* 390 */         int pos = 1;
/* 391 */         pos = DbMailItem.setMailboxId(revDumpstmt, mbox, pos);
/* 392 */         for (Iterator i$ = rev_itemIds.keySet().iterator(); i$.hasNext();) { itemId = (Integer)i$.next();
/* 393 */           Object revs = rev_itemIds.get(itemId);
/* 394 */           for (i$ = ((Collection)revs).iterator(); i$.hasNext();) { int rev = ((Integer)i$.next()).intValue();
/* 395 */             revDumpstmt.setString(pos++, itemId + "-" + rev); } }
/*     */         Integer itemId;
/*     */         Iterator i$;
/* 398 */         revDumpstmt.execute();
/*     */       } catch (SQLException e) {
/* 400 */         throw ServiceException.FAILURE("deleting " + idRevs.size() + " item(s): " + DbMailItem.getIdListForLogging(idRevs.keys()) + " from " + "revision_dumpster" + " table", e);
/*     */       }
/*     */       finally {
/* 403 */         DbPool.quietCloseStatement(revDumpstmt);
/*     */       }
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/db/DbBlobConsistency.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */